import { cwd } from 'node:process'
import { nodeServerWrap } from '../src/adapter'
import Easy, { LRUCache } from '../src/index'
import jwt from '../src/middleware'
import { useCache } from '../src/utils'
import docRegister from './doc'
import busiRes from './utils/busi-res'

declare module '../src/index' {
  interface CustomContext {
    /**
     * 获取当前时间戳
     */
    addTime: () => number
    /**
     * 业务成功
     */
    busiSuc: (data: any) => void
    // 其他自定义属性
    cache: <R>(this: void, key: string, func: (cacheKey?: string) => R | Promise<R>, expire?: number | `${number}m` | `${number}h` | `${number}d`) => Promise<R> | R
  }
  interface CustomState {
    userInfo: {
      name: string
      id: number
      role: string
      token: string
    }
  }
}

const config = {
  debug: false, // 输出调试信息
  baseDir: cwd(), // 应用根目录
  controllerDir: 'examples/service',
}

const app = new Easy(config)
Object.keys(busiRes).forEach((key) => {
  app.context[key] = busiRes[key]
})
const mapCache = new LRUCache(1000)
const cache = useCache({
  set: (key, data, expire) => {
    const iat = Date.now()
    let exp
    if (expire > 0) {
      exp = iat + expire
    }
    mapCache.set(key, { data, exp, iat })
    return data
  },
  get: (key) => {
    const cache = mapCache.get(key)
    if (!cache) return null
    if (cache.exp && Date.now() > cache.exp) {
      mapCache.remove(key)
      return null
    }
    return cache.data
  },
  del: (key) => {
    mapCache.remove(key)
  },
})
app.context.cache = cache
// app.use(staticDir(path.join(config.baseDir, 'public')))
app.use(jwt.jwt({ secret: 'secret', unless: [/user/, /article/, /^\/system/] }))
docRegister(app)

// 前置钩子
app.on('request', (ctx, next) => {
  if (ctx.request.path === '/user/login') {
    // ctx.throw(401, 'Unauthorized')
    // 终止后续钩子
  }
  next()
})

// 响应后钩子（记录日志）
app.on('response', (ctx, next) => {
  next()
})

// 错误处理钩子
app.on('error', (err, ctx, next) => {
  console.error('全局错误:', err)
  // ctx.response.send({ error: 'Internal Server Error', err })
  next()
})

nodeServerWrap(app.serve, 3000)
